package com.example.mqttcar.websocket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * WebSocket消息处理
 *
 * @author ruoyi
 */
@Component
@ServerEndpoint("/websocket/{sid}/{role}")
public class WebSocketServer {
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);

    // 存放每个客户端对应的WebSocketServer对象
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
    //设置为静态的 公用一个消息map ConcurrentMap为线程安全的map  HashMap不安全
    private static ConcurrentMap<String, Map<String, List<Object>>> messageMap=new ConcurrentHashMap<>();

    private Session session;
    private String sid = ""; // 用户ID
    private String role = ""; // 角色标识（例如"admin"或"user"）

    // 当前在线连接数
    private static int onlineCount = 0;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid, @PathParam("role") String role) {
        this.session = session;
        this.sid = sid;
        this.role = role;
        webSocketSet.add(this); // 加入set中
        addOnlineCount(); // 在线数加1

        LOGGER.info("有新窗口开始监听: sid={}, role={}, 当前在线人数为: {}", sid, role, getOnlineCount());
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发送消息给特定用户
     *
     * @param message 要发送的消息内容
     * @param sid     目标用户的会话标识符（Session ID）
     * @param role    目标用户的角色
     */
    public void sendToSpecificUser(String message, String sid, String role) throws IOException {
        LOGGER.info("推送消息到窗口: sid={}, role={}, 推送内容: {}", sid, role, message);

        for (WebSocketServer item : webSocketSet) {
            if (item.sid.equals(sid) && item.role.equals(role) && item.session != null && item.session.isOpen()) {
                item.session.getBasicRemote().sendText(message);
                // 找到目标用户后，无需继续循环
                break;
            }
        }
    }

    /**
     * 群发自定义消息
     */
    public static void sendInfoToAllUser(String message) throws IOException {
        LOGGER.info("推送消息到所有用户，推送内容: {}", message);

        for (WebSocketServer item : webSocketSet) {
            if (item.session != null && item.session.isOpen()) {
                item.session.getBasicRemote().sendText(message);
            }
        }
    }

    /**
     * 群发自定义消息给特定角色
     *
     * @param message 要发送的消息内容
     * @param role    目标角色
     */
    public static void sendInfoToRole(String message, String role) throws IOException {
        LOGGER.info("推送消息到角色: {}, 推送内容: {}", role, message);

        for (WebSocketServer item : webSocketSet) {
            if (item.role.equals(role) && item.session != null && item.session.isOpen()) {
                item.session.getBasicRemote().sendText(message);
            }
        }
    }

    /**
     * 连接关闭时处理
     */
    @OnClose
    public void onClose(Session session) {
        LOGGER.info("关闭连接: {}", session);
        webSocketSet.remove(this); // 从set中移除
        subOnlineCount(); // 在线数减1
    }

    /**
     * 抛出异常时处理
     */
    @OnError
    public void onError(Session session, Throwable exception) {
        LOGGER.error("连接异常: {}", session);
        LOGGER.error("异常信息: {}", exception.getMessage());
        webSocketSet.remove(this); // 从set中移除
        subOnlineCount(); // 在线数减1
    }

    /**
     * 服务器接收到客户端消息时调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        LOGGER.info("收到来自窗口: sid={}, role={} 的消息: {}", sid, role, message);
        // 可以根据角色进行不同的处理逻辑
        if ("admin".equals(role)) {
            // 处理管理员消息
        } else if ("user".equals(role)) {
            // 处理用户消息
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        onlineCount--;
    }
}
